﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ares.Engine;
using System.ComponentModel;
using System.Windows.Input;
using Ares.Controller;
using System.Windows;
using System.Windows.Media;

//Red
//OperationColor = new SolidColorBrush(Color.FromArgb(204, 203, 0, 0));

//Green
//OperationColor = new SolidColorBrush(Color.FromArgb(204, 72, 203, 0));

//Orange
//OperationColor = new SolidColorBrush(Color.FromArgb(204, 255, 152, 41));

namespace Ares.GUI.Models
{
    public class BackupContainerComparer : IEqualityComparer<BackupContainer>
    {
        public bool Equals(BackupContainer x, BackupContainer y)
        {
            //return (x.ToLower() == y.ToLower());
            return (x.ProjectPath.ToLower() == y.ProjectPath.ToLower() && 
                    x.Project.Source.ToLower() == y.Project.Source.ToLower() &&
                    x.Project.Destination.ToLower() == y.Project.Destination.ToLower());
        }

        public int GetHashCode(BackupContainer obj)
        {
            return obj.GetHashCode();
        }
    }

    public class BackupProgress : INotifyPropertyChanged
    {
        private double progress;
        private double progressMax;
        private string statusMessage;

        public double Progress {
            get
            {
                return progress;
            }
            set
            {
                progress = value;
                OnPropertyChanged("Progress");
            }
        }
        public double ProgressMax
        {
            get
            {
                return progressMax;
            }
            set
            {
                progressMax = value;
                OnPropertyChanged("ProgressMax");
            }
        }
        public string StatusMessage
        {
            get
            {
                return statusMessage;
            }
            set
            {
                statusMessage = value;
                OnPropertyChanged("StatusMessage");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises the PropertyChanged event
        /// </summary>
        /// <param name="propertyName">The property name</param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class BackupContainer : BaseController
    {
        private bool canStartRevert;

        public bool CanStartRevert
        {
            get
            {
                return canStartRevert;
            }
            set
            {
                canStartRevert = value;
                OnPropertyChanged("CanStartRevert");
            }
        }

        private Visibility progressVisible;
        private Visibility controlsVisible;

        private SolidColorBrush operationColor;
        private BackgroundWorker bWorker;
        private BackupProgress progress;
        private Boolean canStartBackup;
        private Visibility controlsVisibility;
        private List<string> backupEngines;

        public List<string> BackupEngines
        {
            get
            {
                return backupEngines;
            }
            set
            {
                backupEngines = value;
                OnPropertyChanged("BackupEngines");
            }
        }

        public Visibility ProgressVisible
        {
            get
            {
                return progressVisible;
            }
            set
            {
                progressVisible = value;
                OnPropertyChanged("ProgressVisible");
            }
        }
        public Visibility ControlsVisible
        {
            get
            {
                return controlsVisible;
            }
            set
            {
                controlsVisible = value;
                OnPropertyChanged("ControlsVisible");
            }
        }

        public SolidColorBrush OperationColor
        {
            get
            {
                return operationColor;
            }
            set
            {
                operationColor = value;
                OnPropertyChanged("OperationColor");
            }
        }

        public Visibility ControlsVisibility
        {

            get { return controlsVisibility; }
            set
            {
                controlsVisibility = value;
                OnPropertyChanged("ControlsVisibility");
            }
        }
        public BackupProgress Progress { 
            
            get { return progress; }
            set
            {
                progress = value;
                OnPropertyChanged("Progress");
            }
        }
        public BackupProject Project { get; set; }
        public Backup BackupClass { get; set; }
        public String ProjectPath { get; set; }
        public String LastBackup { get; set; }
        public Boolean CanStartBackup
        {

            get { return canStartBackup; }
            set
            {
                canStartBackup = value;
                OnPropertyChanged("CanStartBackup");
            }
        }

        private ICommand backupCommand;
        private ICommand revertCommand;
        private ICommand editCommand;
        private ICommand deleteCommand;

        public ICommand RevertCommand
        {
            get
            {
                if (this.revertCommand == null)
                    this.revertCommand = new RelayCommand(p => this.DoRevert(p), () => this.CanDoRevert());

                return this.revertCommand;
            }
        }

        public ICommand BackupCommand
        {
            get
            {
                if (this.backupCommand == null)
                    this.backupCommand = new RelayCommand(p => this.DoBackup(p), () => this.CanDoBackup());

                return this.backupCommand;
            }
        }

        public ICommand EditCommand
        {
            get
            {
                if (this.editCommand == null)
                    this.editCommand = new RelayCommand(p => this.DoEdit(p), () => this.CanDoEdit());

                return this.editCommand;
            }
        }

        public ICommand DeleteCommand
        {
            get
            {
                if (this.deleteCommand == null)
                    this.deleteCommand = new RelayCommand(p => this.DoDelete(p), () => this.CanDoDelete());

                return this.deleteCommand;
            }
        }

        public BackupContainer(BackupProject project, String projectPath)
        {
            Project = project;
            ProjectPath = projectPath;
            BackupEngines = new List<string>();
            OperationColor = new SolidColorBrush(Color.FromArgb(204, 72, 203, 0));
            ControlsVisible = Visibility.Visible;
            ProgressVisible = Visibility.Hidden;
            if (BackupClass == null)
                BackupClass = new Backup();
            BackupClass.OnSaveProgressHandler += new SaveProgressHandler(BackupClass_OnSaveProgressHandler);
            BackupClass.OnCalculationProgressHandler += new CalculationProgressHandler(BackupClass_OnCalculationProgressHandler);
            bWorker = new BackgroundWorker();
            bWorker.DoWork += new DoWorkEventHandler(bWorker_DoWork);
            bWorker.ProgressChanged += new ProgressChangedEventHandler(bWorker_ProgressChanged);
            bWorker.WorkerReportsProgress = true;
            bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bWorker_RunWorkerCompleted);
            
            CanStartBackup = true;
            CanStartRevert = true;
            BackupEngines = BackupClass.GetAllExtensionNames();
            //Set default storage engine

            if (BackupClass.GetLastBackupDate() == DateTime.MinValue)
            {
                LastBackup = "Not yet run.";
            }
            else
            {
                LastBackup = BackupClass.GetLastBackupDate().ToString();
            }


        }

        void BackupClass_OnCalculationProgressHandler(object sender, CalculationProgressEvent e)
        {
            BackupProgress progress = new BackupProgress();
            progress.Progress = Convert.ToDouble(e.Progress);
            progress.ProgressMax = Convert.ToDouble(e.Total);
            progress.StatusMessage = e.StatusText;

            bWorker.ReportProgress(0, progress);
        }

        void bWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            CanStartBackup = true;

            ControlsVisible = Visibility.Visible;
            ProgressVisible = Visibility.Hidden;
            //Green again
            OperationColor = new SolidColorBrush(Color.FromArgb(204, 72, 203, 0));
        }

        void bWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState != null)
            {
                Progress = (BackupProgress)e.UserState;
            }
        }

        void bWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            CanStartBackup = false;
            BackupClass.DoBackup();
        }

        void BackupClass_OnSaveProgressHandler(object sender, SaveProgressEvent e)
        {
            BackupProgress progress = new BackupProgress();
            progress.Progress = Convert.ToDouble(e.Progress);
            progress.ProgressMax = Convert.ToDouble(e.Total);
            progress.StatusMessage = e.StatusText;

            bWorker.ReportProgress(0, progress);
            
        }

        public void DoBackup(object p)
        {
            if (!bWorker.IsBusy)
            {
                OperationColor = new SolidColorBrush(Color.FromArgb(204, 255, 152, 41));
                ProgressVisible = Visibility.Visible;
                ControlsVisible = Visibility.Hidden;
                BackupClass.SetBackupStorageEngine(Project.StorageEngine);
                BackupClass.SetProjectDestination(Project.Destination);
                BackupClass.SetProjectName(Project.Name);
                BackupClass.SetProjectSource(Project.Source);
                BackupClass.SetProjectType(Project.Method);
                bWorker.RunWorkerAsync();
            }

        }

        private bool CanDoBackup()
        {
            return CanStartBackup;
        }

        public void DoRevert(object p)
        {
            OperationColor = new SolidColorBrush(Color.FromArgb(204, 255, 152, 41));
            BackupClass.SetBackupStorageEngine(Project.StorageEngine);
            BackupClass.SetProjectDestination(Project.Destination);
            BackupClass.SetProjectName(Project.Name);
            BackupClass.SetProjectSource(Project.Source);
            BackupClass.SetProjectType(Project.Method);
            Mediator.NotifyColleagues(Messages.RevertProject, this);
        }

        private bool CanDoRevert()
        {
            return CanStartRevert;
        }

        public void DoEdit(object p)
        {
            BackupClass.SetBackupStorageEngine(Project.StorageEngine);
            BackupClass.SetProjectDestination(Project.Destination);
            BackupClass.SetProjectName(Project.Name);
            BackupClass.SetProjectSource(Project.Source);
            BackupClass.SetProjectType(Project.Method);
            Mediator.NotifyColleagues(Messages.EditProject, this);
        }

        private bool CanDoEdit()
        {
            return true;
        }

        public void DoDelete(object p)
        {

        }

        private bool CanDoDelete()
        {
            return false;
        }

        public override void MessageNotification(string message, object args)
        {
            switch (message)
            {
                case Messages.SaveProject:
                    OnPropertyChanged("Project");
                    break;
            }
        }
    }
}
